package com.peas.platform.common.core.controller.vo;

import lombok.Data;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.LinkedHashSet;
import java.util.Set;

@Data
public class GarbageCollectorInfo {

    private Long jvmGcCount;
    private Long jvmGcTime;
    private Long jvmFullgcCount;
    private Long jvmFullgcTime;
    private Long jvmYounggcCount;
    private Long jvmYounggcTime;
    private Long jvmYounggcMeantime;

    private Long lastGcTime;
    private Long lastGcCount;
    private Long lastFullgcTime;
    private Long lastFullgcCount;
    private Long lastYounggcTime;
    private Long lastYounggcCount;

    private final Set<String> younggcAlgorithm = new LinkedHashSet<String>() {
        {
            add("Copy");
            add("ParNew");
            add("PS Scavenge");
            add("G1 Young Generation");
        }
    };

    private final Set<String> oldgcAlgorithm = new LinkedHashSet<String>() {
        {
            add("MarkSweepCompact");
            add("PS MarkSweep");
            add("ConcurrentMarkSweep");
            add("G1 Old Generation");
        }
    };

    public GarbageCollectorInfo() {
        collectGC();
    }

    private void collectGC() {
        long gcTime = 0;
        long gcCount = 0;
        long oldGcTime = 0;
        long oldGCount = 0;
        long youngGcTime = 0;
        long youngGcCount = 0;
        for (final GarbageCollectorMXBean garbageCollector : ManagementFactory.getGarbageCollectorMXBeans()) {
            gcTime += garbageCollector.getCollectionTime();
            gcCount += garbageCollector.getCollectionCount();
            String gcAlgorithm = garbageCollector.getName();
            if (younggcAlgorithm.contains(gcAlgorithm)) {
                youngGcTime += garbageCollector.getCollectionTime();
                youngGcCount += garbageCollector.getCollectionCount();
            } else if (oldgcAlgorithm.contains(gcAlgorithm)) {
                oldGcTime += garbageCollector.getCollectionTime();
                oldGCount += garbageCollector.getCollectionCount();
            }
        }
        //
        //   GC实时统计信息
        //
        jvmGcTime = gcTime - (lastGcTime == null ? 0 : lastGcTime);
        jvmGcCount = gcCount - (lastGcCount == null ? 0 : lastGcCount);
        jvmFullgcTime = oldGcTime - (lastFullgcTime == null ? 0 : lastFullgcTime);
        jvmFullgcCount = oldGCount - (lastFullgcCount == null ? 0 : lastFullgcCount);
        jvmYounggcTime = youngGcTime - (lastYounggcTime == null ? 0 : lastYounggcTime);
        jvmYounggcCount = youngGcCount - (lastYounggcCount == null ? 0 : lastYounggcCount);
        if (youngGcCount > (lastYounggcCount == null ? 0 : lastYounggcCount)) {
            jvmYounggcMeantime = (youngGcTime - (lastYounggcCount == null ? 0 : lastYounggcCount)) / (youngGcCount - (lastYounggcCount == null ? 0 : lastYounggcCount));
        } else {
            jvmYounggcMeantime = 0L;
        }
        //
        //  GC增量统计信息
        //
        lastGcTime = gcTime;
        lastGcCount = gcCount;
        lastYounggcCount = youngGcCount;
        lastYounggcTime = youngGcTime;
        lastFullgcCount = oldGCount;
        lastFullgcTime = oldGcTime;
    }

}
